#ifndef __ENUMERATIONS_H__
#define __ENUMERATIONS_H__

/*mesh*/
// 读入数据的类型
typedef enum MESHDATATYPE
{
    LINETYPE = 0,
    MATLAB,
    SIMPLEX
} MESHDATATYPE;
// 网格类型
typedef enum MESHTYPE
{
    LINEMESH,
    TRIANGLE = 0,
    TETHEDRAL
} MESHTYPE;

#define N_TypeBound 6
typedef enum BOUNDARYTYPE
{
    INNER = 0,
    DIRICHLET,
    NEUMANN,
    ROBIN,
    NOTBOUNDARY,
    STIFFDIRICHLET,
    MASSDIRICHLET
} BOUNDARYTYPE;
#define NumFemType 21
typedef enum FEMTYPE
{
    D_L_P0_1D,
    C_L_P1_1D,
    C_T_P1_2D,
    C_T_P2_2D,
    C_T_P3_2D,
    D_T_P0_2D,
    D_T_P1_2D,
    C_T_CR_2D,
    C_T_P1_2D_2D,
    C_T_P2_2D_2D,
    C_T_P3_2D_2D,
    C_T_CR_2D_2D,
    C_T_P1_3D,
    C_T_P2_3D,
    C_T_P3_3D,
    C_T_P4_3D,
    C_T_P5_3D,
    C_T_P1_3D_3D,
    C_T_P2_3D_3D,
    C_T_P3_3D_3D,
    C_T_P4_3D_3D,
    C_T_P5_3D_3D,
    Curl_T_P1_3D_3D,
    Curl_T_P2_3D_3D,
    Curl_T_P3_3D_3D,
    Curl_T_P4_3D_3D,
    Curl_T_P5_3D_3D,
    Div_T_P1_3D_3D,
    Div_T_P2_3D_3D,
} FEMTYPE;

#define N_MultiIndices1D 3  // 0,1,2阶导数
#define N_MultiIndices2D 6  // 0,1,2阶导数
#define N_MultiIndices3D 10 // 0,1,2阶导数
typedef enum MULTIINDEX
{
    D0 = 0,
    D1,
    D2,
    D00,
    D10,
    D01,
    D20,
    D11,
    D02,
    D000,
    D100,
    D010,
    D001,
    D200,
    D020,
    D002,
    D110,
    D101,
    D011
} MULTIINDEX;
#define N_MapType 3
typedef enum MAPTYPE
{
    Affine = 0,
    CR,
    Piola,
    Div,
    Actual
} MAPTYPE;

#define DIV_2D_INDEX_NUM 2
#define DIV_2D_INDEX D10, D01
#define DIV_2D(value, indexpos) (value[indexpos * 2] + value[indexpos * 2 + 3])
#define DIV_3D_INDEX_NUM 3
#define DIV_3D_INDEX D100, D010, D001
#define DIV_3D(value, indexpos) (value[indexpos * 3] + value[indexpos * 3 + 4] + value[indexpos * 3 + 8])
#define CURL_3D_INDEX_NUM 3
#define CURL_3D_INDEX D100, D010, D001
#define CURL_3D_X(value, indexpos) (value[indexpos * 3 + 5] - value[indexpos * 3 + 7])
#define CURL_3D_Y(value, indexpos) (value[indexpos * 3 + 6] - value[indexpos * 3 + 2])
#define CURL_3D_Z(value, indexpos) (value[indexpos * 3 + 1] - value[indexpos * 3 + 3])

#define N_QuadType 13
typedef enum QUADRATURETYPE
{
    QuadLine1 = 0,
    QuadLine2,
    QuadLine3,
    QuadLine4,
    QuadLine5,
    QuadLine6,
    QuadLine8,
    QuadLine12,
    QuadLine16,
    QuadTriangle1,
    QuadTriangle3,
    QuadTriangle4,
    QuadTriangle7,
    QuadTriangle13,
    QuadTriangle27,
    QuadTriangle36,
    QuadTetrahedral1,
    QuadTetrahedral4,
    QuadTetrahedral11,
    QuadTetrahedral15,
    QuadTetrahedral35,
    QuadTetrahedral56,
    QuadTetrahedral127,
    QuadTetrahedral304
} QUADRATURETYPE;

// add 矩阵 向量的存储类型
typedef const char *DATATYPE;
#define TYPE_PETSC "PETSc"
#define TYPE_OPENPFEM "OpenPFEM"
// #define TYPE_SLEPC "SLPEc"
#define TYPE_SLEPC TYPE_PETSC
#define DataTypePetscEqual(type) ((strcmp(TYPE_PETSC, type)) ? false : true)
#define DataTypeSlepcEqual(type) ((strcmp(TYPE_SLEPC, type)) ? false : true)
#define DataTypeOpenPFEMEqual(type) ((strcmp(TYPE_OPENPFEM, type)) ? false : true)
#define DataTypeEqual(type1, type2) ((strcmp(type1, type2)) ? false : true)

typedef const char *SOLVERTYPE;

#define PETSC_KSPCG "PETSc_KSPCG"
#define PETSC_SUPERLU "PETSc_PCLU_SUPERLU_DIST"
#define MULTILEVEL_LINEAR "Multilevel"
#define SolverTypeEqual_PETSC_KSPCG(type) ((strcmp(PETSC_KSPCG, type)) ? false : true)
#define SolverTypeEqual_PETSC_SUPERLU(type) ((strcmp(PETSC_SUPERLU, type)) ? false : true)
#define SolverTypeEqual_MULTILEVEL_LINEAR(type) ((strcmp(MULTILEVEL_LINEAR, type)) ? false : true)

#define SLEPC_KRYLOVSCHUR "SLEPc_KrylovSchur"
#define GCGE "gcge"
#define SolverTypeEqual_GCGE(type) ((strcmp(GCGE, type)) ? false : true)
#define MULTILEVEL_PASE "PASE"
#define SolverTypeEqual_SLEPC_KRYLOVSCHUR(type) ((strcmp(SLEPC_KRYLOVSCHUR, type)) ? false : true)
#define SolverTypeEqual_PASE(type) ((strcmp(MULTILEVEL_PASE, type)) ? false : true)


// 矩阵格式对比
typedef const char *NONZERO_STRUCT;
#define NONZERO_SAME "nonzero_same_structure"
#define NONZERO_SUBSET "nonzero_subset_structure"
#define NONZERO_DIFF "nonzero_different_structure"

#endif